package cn.xinfei.xdecision.common.service.component.guiderule.impl;

import cn.hutool.core.date.DateUtil;
import cn.xinfei.xdecision.common.QueryWrapperX;
import cn.xinfei.xdecision.common.dao.component.guiderule.RuleInfoMapper;
import cn.xinfei.xdecision.common.dao.component.scriptrule.RuleScriptFieldRelMapper;
import cn.xinfei.xdecision.common.model.common.requestParam.UpdateStatusParam;
import cn.xinfei.xdecision.common.model.component.ComponentVersionVo;
import cn.xinfei.xdecision.common.model.component.ComponentVo;
import cn.xinfei.xdecision.common.model.component.CopyToFolderReqVo;
import cn.xinfei.xdecision.common.model.component.dependency.EngineNodeComponentRel;
import cn.xinfei.xdecision.common.model.component.dependency.resp.DecisionComponentDependencyResp;
import cn.xinfei.xdecision.common.model.component.guiderule.RuleInfo;
import cn.xinfei.xdecision.common.model.component.guiderule.RuleVersion;
import cn.xinfei.xdecision.common.model.component.guiderule.vo.RuleListReqVo;
import cn.xinfei.xdecision.common.model.component.guiderule.vo.RuleListRespVo;
import cn.xinfei.xdecision.common.model.component.guiderule.vo.RuleVersionVo;
import cn.xinfei.xdecision.common.model.component.guiderule.vo.RuleVo;
import cn.xinfei.xdecision.common.model.component.scriptrule.RuleScriptVersion;
import cn.xinfei.xdecision.common.model.login.SessionManager;
import cn.xinfei.xdecision.common.service.common.sso.SSOService;
import cn.xinfei.xdecision.common.service.common.sso.dto.SSOUserInfoRespDto;
import cn.xinfei.xdecision.common.service.component.ComponentCommonContext;
import cn.xinfei.xdecision.common.service.component.ComponentCommonService;
import cn.xinfei.xdecision.common.service.component.dependency.EngineNodeComponentRelService;
import cn.xinfei.xdecision.common.service.component.guiderule.RuleService;
import cn.xinfei.xdecision.common.service.component.guiderule.RuleVersionService;
import cn.xinfei.xdecision.common.service.component.scriptrule.RuleScriptVersionService;
import cn.xinfei.xdecision.common.service.utils.CodeGenerateUtil;
import cn.xinfei.xdecision.common.utils.constant.SysConstant;
import cn.xinfei.xdecision.common.utils.constant.strategyx.RuleConst;
import cn.xinfei.xdecision.common.utils.enums.enginex.*;
import cn.xinfei.xdecision.common.utils.exception.ApiException;
import cn.xinfei.xdecision.common.utils.exception.enums.ErrorCodeEnum;
import cn.xinfei.xdecision.common.utils.util.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

import static cn.xinfei.xdecision.common.utils.exception.enums.ErrorCodeEnum.*;
import static cn.xinfei.xdecision.common.utils.exception.util.ApiExceptionUtil.exception;

/**
 * 组织规则维护表(RuleInfo)表服务实现类
 */
@Service("ruleService")
@Slf4j
public class RuleServiceImpl extends ServiceImpl<RuleInfoMapper, RuleInfo> implements RuleService, ComponentCommonService {
    @Resource
    private RuleInfoMapper ruleInfoMapper;
    @Resource
    private RuleVersionService versionService;
    @Resource
    private RuleScriptVersionService ruleScriptVersionService;
    @Resource
    private SSOService ssoService;
    @Resource
    private CodeGenerateUtil codeGenerateUtil;
    @Resource
    private EngineNodeComponentRelService engineNodeComponentRelService;
    @Resource
    private RuleScriptFieldRelMapper ruleScriptFieldRelMapper;

    @Resource(name = "componentAsyncExecutor")
    private ExecutorService bizProcessorThreadPool;

    @Resource
    private TransactionTemplate transactionTemplate;

    @Resource
    private RuleServiceImpl ruleService;

    @Override
    public RuleVo queryById(Long id) {
        RuleVo ruleVo = new RuleVo();
        //主表信息
        RuleInfo ruleInfo = this.getById(id);
        if (Objects.isNull(ruleInfo)) {
            return ruleVo;
        }
        BeanUtils.copyProperties(ruleInfo, ruleVo);
        //规则状态描述
        ruleVo.setStatusDesc(Objects.requireNonNull(ComponentStatusEnum.get(ruleVo.getStatus())).getName());
        int difficulty = ruleInfo.getDifficulty();
        //全部版本信息
        switch (difficulty) {
            case 2:
                //查询版本详情
                List<RuleVersionVo> ruleVersionList = versionService.queryVersionInfoByRuleId(id);
                if (Objects.isNull(ruleVersionList)) {
                    return ruleVo;
                }
                //最新版本
                RuleVersionVo ruleVersionVo = ruleVersionList.stream()
                        .max(Comparator.comparing(RuleVersionVo::getVersionNo)).orElse(null);
                if (Objects.isNull(ruleVersionVo)) {
                    return ruleVo;
                }

                ruleVo.setLastVersionStatus(ruleVersionVo.getStatus())
                        //最新版本状态描述
                        .setLastVersionStatusDesc(Objects.requireNonNull(ComponentVersionStatusEnum.get(ruleVersionVo.getStatus())).getName())
                        //当前版本
                        .setLastVersion(ruleVersionVo.getVersionNo())
//						//版本说明
//						.setVersionDesc(ruleInfo.getDescription())
                        //是否存在新建版本
                        .setIsNewVersion(ruleVersionList.stream().anyMatch(x -> Objects.equals(x.getStatus(), EngineVersionStatusEnum.NEW.getStatus())))
                        .setRuleVersionList(Collections.singletonList(ruleVersionVo));
                ruleVo.setLastVersionNoDesc("V" + ruleVo.getLastVersion());
                break;
            case 3:
                //脚本规则集
                List<RuleScriptVersion> ruleScriptVersionList = ruleScriptVersionService.queryVersionListByRuleId(id);
                //最新版本
                RuleScriptVersion ruleScriptVersion = ruleScriptVersionList.stream()
                        .max(Comparator.comparing(RuleScriptVersion::getVersionNo)).orElse(null);
                if (Objects.isNull(ruleScriptVersion)) {
                    return ruleVo;
                }
                ruleVo.setLastVersionStatus(ruleScriptVersion.getStatus())
                        //最新版本状态描述
                        .setLastVersionStatusDesc(Objects.requireNonNull(ComponentVersionStatusEnum.get(ruleScriptVersion.getStatus())).getName())
                        //当前版本
                        .setLastVersion(ruleScriptVersion.getVersionNo())
//						//版本说明
//						.setVersionDesc(ruleInfo.getDescription())
                        //是否存在新建版本
                        .setIsNewVersion(ruleScriptVersionList.stream().anyMatch(x -> Objects.equals(x.getStatus(), EngineVersionStatusEnum.NEW.getStatus())))
                        .setRuleScriptVersionList(Collections.singletonList(ruleScriptVersion));
                ruleVo.setLastVersionNoDesc("V" + ruleVo.getLastVersion());
                break;
        }

        SSOUserInfoRespDto userInfo = ssoService.getUserInfoById(ruleVo.getUpdateUserId());
        if (userInfo != null) {
            ruleVo.setUpdatedUserName(ssoService.getUserInfoById(ruleVo.getUpdateUserId()).getName());
        }
        return ruleVo;
    }

    @Override
    public RuleInfo queryByCode(String code, Long versionNo) {

        LambdaQueryWrapper<RuleInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(RuleInfo::getCode, code);
//        queryWrapper.eq(RuleInfo::getVersionNo, versionNo);
        return this.getOne(queryWrapper);

    }

    @Override
    public RuleInfo queryByCode(String code) {
        QueryWrapper<RuleInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("code", code);

        return this.getOne(queryWrapper);
    }


    @Override
    public PageInfo getRuleList(RuleListReqVo ruleListReqVo) {
        List<Long> orgIdList = SessionManager.getLoginAccount().getOrgIdList();
        if (org.springframework.util.CollectionUtils.isEmpty(orgIdList)) {
            return new PageInfo<>();
        }
        Integer pageNo = ruleListReqVo.getPageNum();
        Integer pageSize = ruleListReqVo.getPageSize();
        QueryWrapperX<RuleInfo> queryWrapperX = new QueryWrapperX<RuleInfo>()
                .eqIfPresent("folder_id", ruleListReqVo.getFolderId())//文件夹id
                .eqIfPresent("difficulty", ruleListReqVo.getDifficulty())//规则类型
                .eqIfPresent("status", ruleListReqVo.getStatus())//规则状态
                .inIfPresent("status", ruleListReqVo.getStatusList())//规则状态列表
                .inIfPresent("organ_id", orgIdList);

        //搜索内容完全匹配code,模糊匹配name
        if (StringUtil.isValidStr(ruleListReqVo.getSearchString())) {
            queryWrapperX.and(tmp -> tmp.eq("code", ruleListReqVo.getSearchString())
                    .or()
                    .like("name", ruleListReqVo.getSearchString()));
        }
        //排序按照启用，更新时间倒序
        queryWrapperX.orderByDesc("status=1", "updated_time");

        PageHelper.startPage(pageNo, pageSize);
        List<RuleInfo> ruleInfoList = ruleInfoMapper.selectList(queryWrapperX);
        PageInfo<RuleInfo> pageInfo = new PageInfo<>(ruleInfoList);

        List<RuleListRespVo> ruleListRespVos = JSONObject.parseArray(JsonUtils.toJsonString(ruleInfoList), RuleListRespVo.class);

        //查询最新版本号
        ruleListRespVos.forEach(ruleInfo -> {
            int difficulty = ruleInfo.getDifficulty();
            if (difficulty == 2) {
                List<RuleVersionVo> versions = versionService.queryVersionListByRuleId(ruleInfo.getId());
                RuleVersionVo lastVersion = versions.stream()
                        .max(Comparator.comparing(RuleVersionVo::getVersionNo)).orElse(new RuleVersionVo());
                ruleInfo.setLastVersion(lastVersion.getVersionNo());
                ruleInfo.setLastVersionDesc("V" + lastVersion.getVersionNo());
                ruleInfo.setRuleVersionList(versions);
            } else if (difficulty == 3) {
                List<RuleScriptVersion> scriptVersions = ruleScriptVersionService.queryVersionListByRuleId(ruleInfo.getId());
                RuleScriptVersion lastScriptVersion = scriptVersions.stream()
                        .max(Comparator.comparing(RuleScriptVersion::getVersionNo)).orElse(new RuleScriptVersion());
                ruleInfo.setLastVersion(lastScriptVersion.getVersionNo());
                ruleInfo.setLastVersionDesc("V" + lastScriptVersion.getVersionNo());
                ruleInfo.setRuleScriptVersionList(scriptVersions);
            }
        });

        ssoService.fillUserInfoToVO(ruleListRespVos);

        PageInfo<RuleListRespVo> pageInfo1 = new PageInfo<>(ruleListRespVos);
        pageInfo1.setTotal(pageInfo.getTotal());
        return pageInfo1;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RuleVo insertRuleInfo(RuleVo vo) {
        if (StringUtils.isEmpty(vo.getName())) {
            throw new ApiException(ErrorCodeEnum.NAME_CAN_NOT_BE_NULL);
        }
        Integer difficulty = vo.getDifficulty();
        if (difficulty == null) {
            throw new ApiException(ErrorCodeEnum.PARAMS_EXCEPTION.getCode(), ErrorCodeEnum.PARAMS_EXCEPTION.getMessage());
        }
        //初始化基本参数,code、name唯一性校验
        checkUniqueness(vo);
        if (vo.getStatus() == null) {
            vo.setStatus(ComponentStatusEnum.NEW.getStatus());
        }
        RuleInfo ruleInfo = new RuleInfo();
        BeanUtils.copyProperties(vo, ruleInfo);

        log.info("[新增规则]规则详情:{}", ruleInfo);

        ruleInfo.setOrganId(SessionManager.getLoginAccount().getOrganId());
        boolean save = save(ruleInfo);
        if (!save) {
            throw new ApiException(ErrorCodeEnum.RULE_SAVE_ERROR.getCode(), ErrorCodeEnum.RULE_SAVE_ERROR.getMessage());
        }
        vo.setId(ruleInfo.getId());
        Long ruleId = ruleInfo.getId();
        String ruleCode = ruleInfo.getCode();
        if (difficulty == RuleConst.DIFFICULTY_COMPLEX) {
            //插入版本表数据
            List<RuleVersionVo> ruleVersionList = vo.getRuleVersionList();
            if (ruleVersionList != null && !ruleVersionList.isEmpty()) {
                for (RuleVersionVo ruleVersionVo : ruleVersionList) {
                    ruleVersionVo.setRuleId(ruleId);
                    ruleVersionVo.setRuleCode(ruleCode);
                }
                versionService.addVersionList(ruleVersionList);
            }
            vo.setRuleVersionList(versionService.queryVersionListByRuleId(ruleId));
        } else if (difficulty == RuleConst.DIFFICULTY_SCRIPT) {
            //脚本规则集插入版本表
            List<RuleScriptVersion> ruleScriptVersionList = vo.getRuleScriptVersionList();
            if (ruleScriptVersionList != null && !ruleScriptVersionList.isEmpty()) {
                for (RuleScriptVersion ruleScriptVersion : ruleScriptVersionList) {
                    ruleScriptVersion.setRuleId(ruleId);
                    ruleScriptVersion.setRuleCode(ruleCode);
                }
                ruleScriptVersionService.addVersionList(ruleScriptVersionList);
            }
            vo.setRuleScriptVersionList(ruleScriptVersionService.queryVersionListByRuleId(ruleId));
        }
        return vo;
    }

    /**
     * 修改数据
     *
     * @param vo 实例对象
     * @return 实例对象
     */
    @Override
    @Transactional
    public RuleVo updateRuleInfo(RuleVo vo) {
        if (vo.getId() == null || vo.getDifficulty() == null) {
            throw new ApiException(ErrorCodeEnum.PARAMS_EXCEPTION.getCode(), ErrorCodeEnum.PARAMS_EXCEPTION.getMessage());
        }
        Integer difficulty = vo.getDifficulty();
        RuleInfo ruleInfo = new RuleInfo();
        BeanUtils.copyProperties(vo, ruleInfo);
        boolean updateResult = this.updateById(ruleInfo);
        if (!updateResult) {
            throw new ApiException(ErrorCodeEnum.SERVER_ERROR.getCode(), ErrorCodeEnum.SERVER_ERROR.getMessage());
        }
        Long ruleId = vo.getId();
        switch (difficulty) {
            case RuleConst.DIFFICULTY_COMPLEX:
                List<RuleVersionVo> ruleVersionList = vo.getRuleVersionList();
                if (ruleVersionList != null && ruleVersionList.size() > 0) {
                    RuleVersionVo ruleVersionVo = ruleVersionList.get(0);
                    ruleVersionVo.setRuleId(vo.getId());
                    ruleVersionVo.setRuleCode(ruleInfo.getCode());
                    versionService.updateVersion(ruleVersionVo);
                }
                vo.setRuleVersionList(versionService.queryVersionInfoByRuleId(ruleId));
                break;
            case RuleConst.DIFFICULTY_SCRIPT:
                List<RuleScriptVersion> ruleScriptVersionList = vo.getRuleScriptVersionList();
                if (ruleScriptVersionList != null && ruleScriptVersionList.size() > 0) {
                    RuleScriptVersion ruleScriptVersion = ruleScriptVersionList.get(0);
                    ruleScriptVersion.setRuleId(ruleId);
                    ruleScriptVersion.setRuleCode(ruleInfo.getCode());
                    ruleScriptVersionService.updateVersion(ruleScriptVersion);
                }
                vo.setRuleScriptVersionList(ruleScriptVersionService.queryVersionListByRuleId(ruleId));
                break;
        }
        return vo;
    }

    /**
     * 通过主键修改状态，支持批量
     */
    @Override
    @Transactional
    public boolean updateStatus(UpdateStatusParam updateStatusReqVo) {
        updateStatusReqVo.paramsCheck();
        List<RuleInfo> ruleInfos = this.listByIds(updateStatusReqVo.getList());

        //1. 校验规则当前状态与目标变更状态是否一致
        String errorMsg = ruleInfos.stream()
                .filter(x -> Objects.equals(x.getStatus(), updateStatusReqVo.getStatus()))
                .map(RuleInfo::getCode).collect(Collectors.joining(SysConstant.COMMA));
        if (StringUtils.isNotEmpty(errorMsg)) {
            throw exception(COMPONENT_STATUS_UPDATE_ERROR, "当前状态与变更状态一致", errorMsg);
        }

        //2. 停用时需校验是否被决策流依赖
        if (ComponentStatusEnum.DISABLE.getStatus().equals(updateStatusReqVo.getStatus())) {
            List<EngineNodeComponentRel> dependencies =
                    engineNodeComponentRelService.getRelByComponentCode(ruleInfos.stream().map(RuleInfo::getCode).collect(Collectors.toList()));
            if (CollectionUtils.isNotEmpty(dependencies)) {
                throw exception(
                        ErrorCodeEnum.COMPONENT_STATUS_UPDATE_ERROR,
                        "存在依赖关系",
                        dependencies.stream()
                                .map(EngineNodeComponentRel::getComponentCode)
                                .distinct()
                                .collect(Collectors.joining(SysConstant.COMMA)));
            }
        }

        LambdaUpdateWrapper<RuleInfo> wrapper = new LambdaUpdateWrapper<>();
        wrapper.in(RuleInfo::getId, updateStatusReqVo.getList());
        RuleInfo info = new RuleInfo();
        info.setStatus(updateStatusReqVo.getStatus());
        return this.update(info, wrapper);
    }

    @Override
    @Transactional
    public boolean updateParent(List<Long> ids, Long parentId) {
        LambdaUpdateWrapper<RuleInfo> wrapper = new LambdaUpdateWrapper<>();
        wrapper.in(RuleInfo::getId, ids);
        RuleInfo info = new RuleInfo();
        info.setFolderId(parentId);
        return this.update(info, wrapper);
    }

    @Override
    public void copyRule(CopyToFolderReqVo copyToFolderReqVo) {
        if (copyToFolderReqVo.getIds().isEmpty()) {
            throw new ApiException(PARAMS_EXCEPTION.getCode(), PARAMS_EXCEPTION.getMessage());
        }

        List<RuleInfo> ruleInfos = ruleInfoMapper.selectBatchIds(copyToFolderReqVo.getIds());
        if (ruleInfos == null || ruleInfos.isEmpty()) {
            throw new ApiException(PARAMS_EXCEPTION.getCode(), PARAMS_EXCEPTION.getMessage());
        }

        Long loginUserId = SessionManager.getLoginUserId();
        List<String> errorCodeList = new CopyOnWriteArrayList<>();
        List<Future<Void>> allFutureList = Lists.newArrayList();
        ruleInfos.forEach(ruleInfo -> allFutureList.add(CompletableFuture.runAsync(() -> {
            RuleVo ruleVo = new RuleVo();
            BeanUtils.copyProperties(ruleInfo, ruleVo);
            String copyName = copyToFolderReqVo.getNamePrefix() + ruleInfo.getName() + copyToFolderReqVo.getNameSuffix();
            ruleVo.setName(copyName);
            ruleVo.setFolderId(copyToFolderReqVo.getFolderId());
            //规则更新人、更新时间修改为最新值，创建人、创建时间与被拷贝规则保持一致
            ruleVo.setUpdateUserId(loginUserId);
            ruleVo.setCreatedTime(ruleInfo.getCreatedTime());
            ruleVo.setUpdatedTime(DateUtil.now());


            if (ruleInfo.getDifficulty() == RuleConst.DIFFICULTY_COMPLEX) {
                List<RuleVersionVo> ruleVersions = versionService.queryVersionInfoByRuleId(ruleInfo.getId());
                ruleVersions.forEach(ruleVersionVo -> {
                    if (CollectionUtils.isNotEmpty(ruleVersionVo.getComponentActionList())) {
                        ruleVersionVo.getComponentActionList().forEach(componentAction -> componentAction.setId(null));
                    }
                });
                ruleVo.setRuleVersionList(ruleVersions);
            } else if (ruleInfo.getDifficulty() == RuleConst.DIFFICULTY_SCRIPT) {
                List<RuleScriptVersion> scriptVersions = ruleScriptVersionService.queryVersionListByRuleId(ruleInfo.getId());
                scriptVersions.forEach(scriptVersion -> {
                    if (CollectionUtils.isNotEmpty(scriptVersion.getComponentActionList())) {
                        scriptVersion.getComponentActionList().forEach(componentAction -> componentAction.setId(null));
                    }
                });
                ruleVo.setRuleScriptVersionList(scriptVersions);
            }
            log.info("[规则复制]待复制规则:{},新规则:{}", ruleInfo, ruleVo);

            transactionTemplate.execute(status -> {
                try {
                    if (Objects.equals(ruleInfo.getDifficulty(), RuleTypeEnum.GENERAL_RULE.getCode())) {
                        ruleVo.setCode(codeGenerateUtil.generateYMDCode(SysConstant.FZGZ_PREFIX, null));
                    } else if (Objects.equals(ruleInfo.getDifficulty(), RuleTypeEnum.SCRIPT_RULE.getCode())) {
                        ruleVo.setCode(codeGenerateUtil.generateYMDCode(SysConstant.JBGZ_PREFIX, null));
                    }
                    ruleService.insertRuleInfo(ruleVo);
                    return Boolean.TRUE;
                } catch (Exception e) {
                    status.setRollbackOnly();
                    log.error("规则复制失败，规则信息==>{}", JSON.toJSONString(ruleInfo), e);
                    errorCodeList.add(ruleInfo.getCode());
                    return Boolean.FALSE;
                }
            });
        }, bizProcessorThreadPool)));
        allFutureList.forEach(x -> FutureUtils.futureGet(x, ErrorCodeEnum.DECISION_COPY_ERROR));
        if (!org.springframework.util.CollectionUtils.isEmpty(errorCodeList)) {
            throw exception(COMPONENT_COPY_ERROR, errorCodeList);
        }
    }


    //唯一性检查
    private boolean checkUniqueness(RuleVo vo) {

        LambdaQueryWrapper<RuleInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(RuleInfo::getName, vo.getName());
        queryWrapper.eq(RuleInfo::getFolderId, vo.getFolderId());
        RuleInfo info = this.getOne(queryWrapper);
        if (info != null) {
            throw new ApiException(GENERAL_RULE_NAME_REPEAT.getCode(), GENERAL_RULE_NAME_REPEAT.getMessage());
        }
        LambdaQueryWrapper<RuleInfo> queryWrapper2 = new LambdaQueryWrapper<>();
        queryWrapper2.eq(RuleInfo::getCode, vo.getCode());
        RuleInfo info2 = this.getOne(queryWrapper2);
        if (info2 != null) {
            throw new ApiException(GENERAL_RULE_CODE_REPEAT.getCode(), GENERAL_RULE_CODE_REPEAT.getMessage());
        }

        return true;
    }

    @Override
    public List<RuleInfo> getRuleList(List<Long> ruleIds) {
        if (!CollectionUtil.isNotNullOrEmpty(ruleIds)) {
            return null;
        }
        return this.listByIds(ruleIds);
    }

    @Override
    public List<Long> queryByFolderId(Long folderId) {
        QueryWrapper<RuleInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("folder_id", folderId);
        queryWrapper.select("id");

        List<Object> ids = this.listObjs(queryWrapper);
        if (ids == null) {
            return null;
        }
        return ids.stream().map(id -> Long.parseLong(id.toString())).collect(Collectors.toList());
    }

    @Override
    public void logicalDeleteRules(List<Long> ids) {
        this.removeByIds(ids);
    }

    @Override
    public Boolean hasNewVersion(String ruleCode) {
        RuleInfo ruleInfo = queryByCode(ruleCode);
        if (ruleInfo == null) {
            throw new ApiException(RULE_NOT_EXISTS.getCode(), RULE_NOT_EXISTS.getMessage());
        }

        int difficulty = ruleInfo.getDifficulty();

        switch (difficulty) {
            case 2:
                List<RuleVersion> newVersions = versionService.getVersionByStatus(ruleCode, ComponentStatusEnum.NEW.getStatus());
                return newVersions != null && !newVersions.isEmpty();
            case 3:
                List<RuleScriptVersion> scriptVersions = ruleScriptVersionService.getVersionByStatus(ruleCode, ComponentStatusEnum.NEW.getStatus());
                return scriptVersions != null && !scriptVersions.isEmpty();
            default:
                return false;
        }
    }

    @Override
    public List<ComponentVo> listComponentInfoByIds(String ids) {
        List<ComponentVo> allComponentVos = new ArrayList<>();
        //主表信息
        List<RuleInfo> ruleInfos = this.listByIds(Arrays.asList(ids.split(SysConstant.COMMA)));
        //复杂规则
        List<RuleInfo> generalRule = ruleInfos.stream()
                .filter(x -> Objects.equals(x.getDifficulty(), RuleTypeEnum.GENERAL_RULE.getCode())).collect(Collectors.toList());

        if (CollectionUtils.isNotEmpty(generalRule)) {
            Map<String, List<RuleVersion>> collect = versionService.queryVersionByRuleCodes(
                    generalRule.stream().map(RuleInfo::getCode).collect(Collectors.toList()), ComponentVersionStatusEnum.ENABLE.getStatus()).stream()
                    .collect(Collectors.groupingBy(RuleVersion::getRuleCode));
            if (collect.isEmpty()) {
                return allComponentVos;
            }
            List<ComponentVo> componentVos = BeanUtilsPlus.copyElements(generalRule, ComponentVo::new);
            componentVos.forEach(x -> {
                        List<ComponentVersionVo> componentVersionVos =
                                BeanUtilsPlus.copyElements(collect.get(x.getCode()), ComponentVersionVo::new);
                        ComponentCommonContext.swapVersionNoDesc(componentVersionVos);
                        x.setVersionList(componentVersionVos)
                                .setStatusDesc(Objects.requireNonNull(ComponentStatusEnum.get(x.getStatus())).getName());
                    }
            );
            allComponentVos.addAll(componentVos);
        }

        //脚本规则集
        List<RuleInfo> scriptRule = ruleInfos.stream()
                .filter(x -> Objects.equals(x.getDifficulty(), RuleTypeEnum.SCRIPT_RULE.getCode())).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(scriptRule)) {
            Map<String, List<RuleScriptVersion>> collect = ruleScriptVersionService.queryVersionByRuleCodes(
                    scriptRule.stream().map(RuleInfo::getCode).collect(Collectors.toList()), ComponentVersionStatusEnum.ENABLE.getStatus()).stream()
                    .collect(Collectors.groupingBy(RuleScriptVersion::getRuleCode));
            if (collect.isEmpty()) {
                return allComponentVos;
            }
            List<ComponentVo> componentVos = BeanUtilsPlus.copyElements(scriptRule, ComponentVo::new);
            componentVos.forEach(x -> {
                        List<ComponentVersionVo> componentVersionVos =
                                BeanUtilsPlus.copyElements(collect.get(x.getCode()), ComponentVersionVo::new);
                        ComponentCommonContext.swapVersionNoDesc(componentVersionVos);
                        x.setVersionList(componentVersionVos)
                                .setStatusDesc(Objects.requireNonNull(ComponentStatusEnum.get(x.getStatus())).getName());
                    }
            );
            allComponentVos.addAll(componentVos);
        }

        return allComponentVos;
    }

    @Override
    public List<DecisionComponentDependencyResp> getComponentCodeByVarCodes(List<String> varCodes) {
        List<DecisionComponentDependencyResp> list = new ArrayList<>(ruleInfoMapper.getComponentCodeByVarCodes(varCodes));
        list.addAll(ruleScriptFieldRelMapper.getComponentCodeByVarCodes(varCodes));
        return list;
    }

    @Override
    public List<String> getFieldCodesByComponentCodes(List<ComponentVo> componentVoList) {
        if (CollectionUtils.isEmpty(componentVoList)) {
            return Collections.emptyList();
        }
        List<String> list = new ArrayList<>(ruleInfoMapper.getFieldCodesByComponentCodes(componentVoList));
        list.addAll(ruleScriptFieldRelMapper.getFieldCodesByConditions(componentVoList));
        return list;
    }

    @Override
    public List<ComponentVo> listComponentInfoByCon(RuleListReqVo ruleListReqVo) {
        List<ComponentVo> list = new ArrayList<>();
        if (Objects.equals(ruleListReqVo.getComponentType(), ComponentTypeEnum.COMPLEX_RULE_BASE.getType())) {
            list = ruleInfoMapper.listGeneralRuleComponentInfoByCon(ruleListReqVo);
        } else if (Objects.equals(ruleListReqVo.getComponentType(), ComponentTypeEnum.SCRIPT_RULE_BASE.getType())) {
            list = ruleInfoMapper.listScriptRuleComponentInfoByCon(ruleListReqVo);
        }
        return list;
    }
}
